#include "Persistor.h"
#include "fstream"
#include "Constantes.h"

Persistor::Persistor(string ruta, int tamanioBloque) {
	this->tamanioBloque = tamanioBloque;
	this->ruta = ruta;
	this->tamanioArchivo = -1;
}

Persistor::~Persistor() {
	this->cerrarArchivo();
}

bool Persistor::crearArchivo(){
	bool exito = true;
	FILE* resultado = fopen(ruta.c_str(),"w+");
	if(resultado)fclose(resultado);
		else exito = false;
	return exito;
}

bool Persistor::abrirArchivo(){
	bool abierto;
	archivo.open(ruta.c_str(), ios::in | ios::out | ios::binary);
	abierto = archivo.is_open();
	if(abierto){
		int inicio,final;
		inicio = archivo.tellg();
		archivo.seekg(0,ios::end);
		final = archivo.tellg();
		tamanioArchivo = final - inicio;
	}
	return abierto;
}

void Persistor::cerrarArchivo(){
	if(archivo.is_open()) archivo.close();
}

int Persistor::renombrarArchivo(string nueva_ruta){
	bool abierto = archivo.is_open();
	if(abierto) archivo.close();
	int retorno = rename(this->ruta.c_str(),nueva_ruta.c_str());
	if(!retorno){
		this->ruta = nueva_ruta;
		if(abierto) archivo.open(ruta.c_str(), ios::in | ios::out | ios::binary);
	}

	return retorno;
}

int Persistor::removerArchivo(){
	return remove(this->ruta.c_str());
}

bool Persistor::guardarBloque (int nroBloque, CadenaBytes cadena){
	return this->guardarNBloques(nroBloque,1,cadena);
}

bool Persistor::guardarNBloques(int nroPrimerBloque,int n, CadenaBytes cadena){
	bool exito = false;
	int tamanioTotal = n * this->tamanioBloque;
	//verifico que el nro de bloque sea valido y que haya suficiente espacio
	if(((nroPrimerBloque) * tamanioBloque + tamanioTotal) <= tamanioArchivo){
		//verifico que el tamanio de la cadena corresponda a la de n bloques
		if(int(cadena.getTamanio()) == n*this->tamanioBloque){
			archivo.seekp(nroPrimerBloque * tamanioBloque);
			archivo.write(cadena.toString().c_str(),cadena.getTamanio());
			exito = true;
		}

	}
	return exito;
}

CadenaBytes Persistor::leerBloque (int nroBloque){
	return this->leerNBloques(nroBloque,1);
}

CadenaBytes Persistor::leerNBloques(int nroPrimerBloque,int n){
	CadenaBytes bloques;
	int tamanioTotal = n * this->tamanioBloque;
	//verifico que el numero de bloque sea valido
	if(((nroPrimerBloque) * tamanioBloque + tamanioTotal) <= tamanioArchivo){
		archivo.seekg(nroPrimerBloque * tamanioBloque);
		char buffer[tamanioTotal];
		archivo.read(buffer,tamanioTotal);
		bloques.agregar(buffer,tamanioTotal,0);
	}
	return bloques;
}

void Persistor::agregarBloque (){
	this->agregarNBloques(1);
}

void Persistor::agregarNBloques(int n){
	CadenaBytes nuevosBloques;
	char vacio = CONST_VACIO;
	for(int i = 0; i< (tamanioBloque*n);i++){
		nuevosBloques.agregarAlFinal(&vacio,sizeof(char));
	}
	archivo.seekp(tamanioArchivo);
	archivo.write(nuevosBloques.toString().c_str(), n*tamanioBloque);
	tamanioArchivo = tamanioArchivo + n*tamanioBloque;

}

int Persistor::getTamanioArchivo(){
	return this->tamanioArchivo;
}

int Persistor::getCantidadBloques(){
	return (this->tamanioArchivo / this->tamanioBloque);
}

string Persistor::getRuta(){
	return this->ruta;
}
